home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 41
/
Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso
/
Aminet
/
gfx
/
show
/
h8ilbm.lha
/
h8ilbm
/
src
/
h8ilbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-12-16
|
23KB
|
590 lines
/*****************************************************************************
h8ilbm - HiQuality-HAM8 IFF-24bit image viewer
Copyright (C) 2000 Michael Henke
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <graphics/displayinfo.h>
#include <proto/reqtools.h>
#include <proto/asyncio.h>
#include <libraries/reqtools.h>
#include <libraries/asyncio.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <devices/inputevent.h>
UBYTE version[]="$VER: h8ilbm 0.1 (Sat 16-Dec-2000)";
UBYTE template[]="FILES/M,MID/K,SMR/S", rtfilename[128];
UBYTE rowbuf0[16*1024*3];
struct RDArgs *rdargs=NULL;
LONG args[3]={0,0,0};
struct ReqToolsBase *ReqToolsBase=NULL;
struct Library *AsyncIOBase=NULL;
WORD ende=0, movekey=0, xoff, yoff;
int check_idcmp(void);
extern void __asm render_h8row( register __a0 UBYTE *rowbuf,
register __d0 UWORD iw16,
register __a1 struct BitMap *bmap,
register __d1 UWORD row );
BOOL alloc_chipmem(UWORD scr_w, UWORD scr_h); /*return: success*/
void free_chipmem(UWORD scr_w, UWORD scr_h);
struct DimensionInfo diminfo;
struct BitMap bmap=
{
2, 2, /* BytesPerRow, Rows */
0, 8, 0, /* Flags, Depth, pad */
0,0,0,0,0,0,0,0 /* Planes */
};
struct Interrupt window_int=
{
NULL,NULL, NT_UNKNOWN, 0, NULL, /* struct Node */
NULL,(void(*)(void))check_idcmp
};
struct NewScreen newscr=
{
0, 0, 99, 99, 8, /* LeftEdge, TopEdge, Width, Height, Depth */
0, 0, 0, /* DetailPen, BlockPen, ViewModes */
AUTOSCROLL|SCREENQUIET|SCREENHIRES|CUSTOMBITMAP|CUSTOMSCREEN|SCREENBEHIND, /* Type */
0, 0, 0, &bmap /* Font, DefaultTitle, Gadgets, CustomBitMap */
};
struct NewWindow newwin=
{
0, 0, 99, 99, /* LeftEdge, TopEdge, Width, Height */
0, 0, /* DetailPen, BlockPen */
IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS, /* IDCMPFlags */
WFLG_RMBTRAP|WFLG_NOCAREREFRESH|WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_BACKDROP, /* Flags */
0, 0, 0, /* FirstGadget, CheckMark, Title */
0, 0, /* Screen, BitMap */
0, 0, 0, 0, /* MinWidth, MinHeight, MaxWidth, MaxHeight */
CUSTOMSCREEN /* Type */
};
static ULONG palette[]=
{
1<<16, /* (count<<16)+first */
0x00000000,0x00000000,0x00000000,
0 /* end marker */
};
struct Screen *myscreen=NULL;
struct Window *mywindow=NULL;
#define ID_FORM 0x464F524D
#define ID_ILBM 0x494C424D
#define ID_BMHD 0x424D4844
#define ID_BODY 0x424F4459
int main(void)
{
int rc=0;
UBYTE **files_pt, *filename, **rowbuf;
ULONG modeid, header[3], r1;
UWORD iw, ih, id, ic, im, v_scr_w, scr_w, v_scr_h, scr_h, scr_w64, iw16, bufmode;
struct rtFileRequester *rtfilereq=NULL;
struct rtFileList *rtfilelist=NULL, *rtfilelist_curr=NULL;
BPTR lock_newdir=NULL, lock_olddir=NULL;
struct AsyncFile *file=NULL;
/*****************************
** read command line arguments
******************************/
rdargs=ReadArgs(template,args,NULL);
printf("\33[1m%s by Smack/Infect!\33[0m\n",&version[6]);
if (!(AsyncIOBase=OpenLibrary("asyncio.library",39)))
{
printf("**unable to open asyncio.library V39+\n");
rc=20; goto exit_clean;
}
files_pt=(UBYTE**)args[0];
modeid=0x8020;
if(args[1])
{
int b=10;
UBYTE *pt=(UBYTE*)args[1];
if(pt[0]=='$') {pt++; b=16;}
if((pt[0]=='0')&&((pt[1]=='x')||(pt[1]=='X'))) {pt+=2; b=16;}
modeid=strtoul(pt,NULL,b);
}
if(ModeNotAvailable(modeid))
{
printf("**screen mode not available: 0x%x\n",modeid);
args[2]=1;
}
/**********************
** screenmode requester
***********************/
if(args[2])
{
if((ReqToolsBase=(struct ReqToolsBase*)OpenLibrary("reqtools.library",38)))
{
struct rtScreenModeRequester *rtsmreq;
if((rtsmreq=rtAllocRequest(RT_SCREENMODEREQ,NULL)))
{
int res=rtScreenModeRequest(rtsmreq, "h8ilbm: select HAM8 screen mode", TAG_DONE);
modeid=rtsmreq->DisplayID;
rtFreeRequest(rtsmreq);
if(!res) goto exit_clean;
}
else
{
rc=10; goto exit_clean;
}
}
else
{
rc=5; goto exit_clean;
}
}
v_scr_w=v_scr_h=0;
if(GetDisplayInfoData(NULL,(UBYTE*)&diminfo,sizeof(struct DimensionInfo),DTAG_DIMS,modeid))
{
v_scr_w=diminfo.TxtOScan.MaxX-diminfo.TxtOScan.MinX+1;
v_scr_h=diminfo.TxtOScan.MaxY-diminfo.TxtOScan.MinY+1;
}
printf(" screen mode: MID=0x%x (%d x %d pixels visible)\n",modeid,v_scr_w,v_scr_h);
/*************************
** allocate file requester
**************************/
if(!files_pt)
{
if(!ReqToolsBase) ReqToolsBase=(struct ReqToolsBase*)OpenLibrary("reqtools.library",38);
if(ReqToolsBase)
{
if(!(rtfilereq=rtAllocRequest(RT_FILEREQ,NULL)))
{
rc=10; goto exit_clean;
}
}
else
{
rc=5; goto exit_clean;
}
}
/****************
** file requester
*****************/
next_filereq:
if(rtfilereq)
{
if(rtfilelist) rtFreeFileList(rtfilelist);
rtfilelist=rtFileRequest( rtfilereq, &rtfilename[0],
"h8ilbm: select IFF-24bit images",
RTFI_Flags, FREQF_MULTISELECT|FREQF_PATGAD,
TAG_DONE );
if(rtfilelist)
{
rtfilelist_curr=rtfilelist;
if(rtfilereq->Dir)
{
lock_newdir=Lock(rtfilereq->Dir,SHARED_LOCK);
lock_olddir=CurrentDir(lock_newdir);
}
}
else goto exit_clean;
}
/****************************************
** the main loop: display all input files
*****************************************/
do
{
if(rtfilelist)
{
if(rtfilelist_curr)
{
filename=rtfilelist_curr->Name;
rtfilelist_curr=rtfilelist_curr->Next;
}
else filename=NULL;
}
else filename=(*files_pt++);
if(!filename) break;
printf("\n file: %s\n",filename);
if((file=OpenAsync(filename,MODE_READ,64*1024)))
{
r1=ReadAsync(file,header,3*4);
if((r1==3*4) && (header[0]==ID_FORM) && (header[2]==ID_ILBM))
{
/*************************
** read IFF-ILBM file info
**************************/
WORD body_found=0, type_error=0;
iw=ih=id=ic=im=0;
do
{
r1=ReadAsync(file,header,2*4);
if(r1!=2*4) type_error=1;
else switch(header[0])
{
case ID_BODY:
body_found=1;
break;
case ID_BMHD:
if(header[1]!=20) type_error=2;
ReadAsync(file,&iw,2);
ReadAsync(file,&ih,2);
SeekAsync(file,4,MODE_CURRENT); /*skip x,y*/
id=ReadCharAsync(file);
im=ReadCharAsync(file); if(im!=1) im=0;
ic=ReadCharAsync(file);
SeekAsync(file,9,MODE_CURRENT); /*skip rest*/
break;
default:
SeekAsync(file,header[1],MODE_CURRENT);
}
} while(!body_found && !type_error);
printf(" type: %d x %d, %d bits%s%s\n",iw,ih,id,(ic==1)?", ByteRun1 compression":"",im?", masking bitplane":"");
if(body_found && !type_error && iw && ih && (id==24) && (ic<=1))
{
UWORD row;
/**********************
** allocate chip memory
***********************/
bufmode=0;
iw16=(iw+15)&(~15);
scr_w=iw*4; scr_h=ih;
scr_w64=(scr_w+63)&(~63);
if(!alloc_chipmem(scr_w64,scr_h))
{
printf(" not enough chip memory for rendered image, switching to buffer mode\n");
bufmode=1;
scr_w=v_scr_w; scr_h=v_scr_h;
scr_w64=(scr_w+63)&(~63);
if(!alloc_chipmem(scr_w64,scr_h))
{
printf("**not enough chip memory for screen.\n");
ende=(-1); /*next image*/
}
}
/*****************************
** allocate fast memory buffer
******************************/
if(bufmode && !ende)
{
rowbuf=AllocMem((ULONG)(ih*sizeof(UBYTE*)),MEMF_CLEAR|MEMF_PUBLIC);
for(row=0;row<ih;row++) if(!(rowbuf[row]=AllocMem(((ULONG)iw16*18L)>>3,MEMF_PUBLIC))) break;
if(row<ih)
{
printf("**not enough memory for image buffer.\n");
ende=(-1); /*next image*/
}
}
/************************
** open screen and window
*************************/
if(!ende)
{
newscr.Width=scr_w;
newscr.Height=scr_h;
myscreen=OpenScreenTags(&newscr,
SA_DisplayID,modeid|HAM_KEY,
SA_Colors32,palette,
SA_Overscan,OSCAN_TEXT,
SA_BackFill,1, /*LAYERS_NOBACKFILL*/
TAG_END,0);
if(!myscreen)
{
printf("**unable to open screen\n");
ende=(-1); /*next image*/
}
}
if(!ende)
{
newwin.Screen=myscreen;
newwin.Width=scr_w;
newwin.Height=scr_h;
mywindow=OpenWindowTags(&newwin,
WA_BackFill,1, /*LAYERS_NOBACKFILL*/
TAG_END,0);
if(!mywindow)
{
printf("**unable to open window\n");
ende=(-1); /*next image*/
}
}
if(!ende)
{
LONG il;
ULONG *ulpt;
Disable();
mywindow->UserPort->mp_Flags=PA_SOFTINT;
mywindow->UserPort->mp_SigTask=(void*)&window_int;
Enable();
ulpt=(ULONG*)bmap.Planes[6];
for(il=(LONG)(scr_w64/32)*(LONG)scr_h;il>0;il--) *ulpt++ = 0x77777777;
ulpt=(ULONG*)bmap.Planes[7];
for(il=(LONG)(scr_w64/32)*(LONG)scr_h;il>0;il--) *ulpt++ = 0xcccccccc;
ScreenToFront(myscreen);
}
/*****************
** read image data
******************/
if(!ende)
{
UWORD plane, bpr=iw16>>3;
UBYTE *rowpt, *rowpt0;
xoff=yoff=0;
if(ic==0) /** compression==cmpNone **/
{
for(row=0;row<ih;row++)
{
if(ende) break;
if(bufmode) rowpt0=rowbuf[row]; else rowpt0=rowbuf0;
rowpt=rowpt0;
for(plane=0;plane<24;plane++)
{
if((plane%8)>1)
{
ReadAsync(file,rowpt,(LONG)bpr);
rowpt+=bpr;
}
else SeekAsync(file,(LONG)bpr,MODE_CURRENT);
}
if(row<scr_h) render_h8row(rowpt0,iw16,&bmap,row);
if(im) SeekAsync(file,(LONG)bpr,MODE_CURRENT);
}
}
else /*if(ic==1)*/ /** compression==cmpByteRun1 **/
{
WORD code, bytes;
UBYTE *rowpt2, repeat;
for(row=0;row<ih;row++)
{
if(ende) break;
if(bufmode) rowpt0=rowbuf[row]; else rowpt0=rowbuf0;
rowpt=rowpt0;
for(plane=0;plane<24;plane++)
{
rowpt2=rowpt;
bytes=bpr;
if((plane%8)>1)
{
while(bytes>0)
{
if((code=ReadCharAsync(file))<0) break;
if(code<=127)
{
code++; bytes-=code;
ReadAsync(file,rowpt2,(LONG)code);
rowpt2+=code;
}
else
{
code=257-code; bytes-=code;
repeat=ReadCharAsync(file);
while(code>0) {*rowpt2++=repeat; code--;}
}
}
rowpt+=bpr;
}
else
{
while(bytes>0)
{
if((code=ReadCharAsync(file))<0) break;
if(code<=127)
{
code++;
SeekAsync(file,(LONG)code,MODE_CURRENT);
bytes-=code;
}
else
{
bytes-=257-code;
ReadCharAsync(file);
}
}
}
}
if(row<scr_h) render_h8row(rowpt0,iw16,&bmap,row);
if(im)
{
bytes=bpr;
while(bytes>0)
{
if((code=ReadCharAsync(file))<0) break;
if(code<=127)
{
code++;
SeekAsync(file,(LONG)code,MODE_CURRENT);
bytes-=code;
}
else
{
bytes-=257-code;
ReadCharAsync(file);
}
}
}
}
}
}
/***************
** display image
****************/
while(!ende)
{
if(movekey)
{
movekey=0;
if(bufmode)
{
WORD xoff2, yoff2, dh=(scr_h<ih) ? scr_h : ih;
if(xoff<0) xoff=0;
if(yoff<0) yoff=0;
if(xoff+scr_w64/4>iw16) xoff=iw16-scr_w64/4;
if(yoff+scr_h>ih) yoff=ih-scr_h;
if(iw16<scr_w64/4) xoff=0;
if(ih<scr_h) yoff=0;
xoff2=xoff, yoff2=yoff;
for(row=0;row<dh;row++) render_h8row(rowbuf[row+yoff2]+xoff2/8,iw16,&bmap,row);
}
else
{
MoveScreen(myscreen,(LONG)(-xoff),(LONG)(-yoff));
xoff=yoff=0;
}
}
else Delay(1);
}
if(ende<0) ende=0; /*next image*/
/****************
** free resources
*****************/
if(mywindow) {CloseWindow(mywindow); mywindow=NULL;}
if(myscreen) {CloseScreen(myscreen); myscreen=NULL;}
if(bufmode)
{
for(row=0;row<ih;row++) if(rowbuf[row]) FreeMem(rowbuf[row],((ULONG)iw16*18L)>>3);
FreeMem(rowbuf,(ULONG)(ih*sizeof(UBYTE*)));
}
free_chipmem(scr_w64,scr_h);
}
else printf("**file type not supported\n");
}
else printf("**not an IFF ILBM file\n");
CloseAsync(file); file=NULL;
}
else printf("**unable to open file\n");
} while(!ende);
if(rtfilelist)
{
if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
if(!ende) goto next_filereq;
}
exit_clean:
if(file) CloseAsync(file);
if(lock_olddir) CurrentDir(lock_olddir);
if(lock_newdir) UnLock(lock_newdir);
if(rtfilelist) rtFreeFileList(rtfilelist);
if(rtfilereq) rtFreeRequest(rtfilereq);
if(ReqToolsBase) CloseLibrary((struct Library*)ReqToolsBase);
if(AsyncIOBase) CloseLibrary(AsyncIOBase);
if(rdargs) FreeArgs(rdargs);
return(rc);
}
int __saveds check_idcmp(void)
{
WORD dist;
struct IntuiMessage *msg;
while((msg=(struct IntuiMessage*)GetMsg(mywindow->UserPort)))
{
switch(msg->Class)
{
case IDCMP_RAWKEY:
dist=8;
if((msg->Qualifier&IEQUALIFIER_LSHIFT)||(msg->Qualifier&IEQUALIFIER_RSHIFT)) dist=32;
if((msg->Qualifier&IEQUALIFIER_LALT)||(msg->Qualifier&IEQUALIFIER_RALT)) dist=9999;
switch(msg->Code)
{
case 0x45: /*ESC*/ ende=1; break;
case 0x44: /*Return*/
case 0x40: /*Space*/ ende=(-1); break;
case 0x4c: /*up*/ yoff-=dist; movekey=msg->Code; break;
case 0x4d: /*down*/ yoff+=dist; movekey=msg->Code; break;
case 0x4e: /*right*/ xoff+=dist; movekey=msg->Code; break;
case 0x4f: /*left*/ xoff-=dist; movekey=msg->Code; break;
}
break;
case IDCMP_MOUSEBUTTONS:
switch(msg->Code)
{
case MENUUP: /*right MB*/ ende=(-1); break;
}
break;
}
ReplyMsg((struct Message*)msg);
}
return(0);
}
BOOL alloc_chipmem(UWORD scr_w, UWORD scr_h)
{
int i;
bmap.BytesPerRow=scr_w/8;
bmap.Rows=scr_h;
for(i=0;i<8;i++) if(!(bmap.Planes[i]=AllocMem((LONG)(scr_w/8)*(LONG)scr_h,MEMF_CHIP|MEMF_CLEAR))) break;
if(i<8)
{
free_chipmem(scr_w,scr_h);
return(FALSE);
}
else return(TRUE);
}
void free_chipmem(UWORD scr_w, UWORD scr_h)
{
int i;
for(i=0;i<8;i++)
{
if(bmap.Planes[i]) FreeMem(bmap.Planes[i],(LONG)(scr_w/8)*(LONG)scr_h);
bmap.Planes[i]=NULL;
}
}